# 模块准备
import pandas as pd
from flask import Flask, render_template, request
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
import cufflinks as cf
import plotly as py
import plotly.graph_objs as go
from pyecharts.charts import *
from pyecharts import options as opts
import re

app = Flask(__name__)


# 读取数据
def read_data():
    return pd.read_excel("top_universities.xlsx",
                         )


df = read_data()
# 删除最后一行数据
df.drop(df.columns[len(df.columns) - 1], axis=1, inplace=True)
# 字符串替换
df.loc[:, "大学"] = df["大学"].str.replace("�?2021", "学").replace("�?", "").replace("?", "").astype('str')
# 香港，澳门，台湾与中国大陆地区等在榜单中是分开的记录的，这边都归为china
df.loc[:, "国家"] = df["国家"].str.replace("China (Mainland)", "China") \
    .replace("Hong Kong SAR", "China") \
    .replace("Taiwan", "China") \
    .replace("Macau SAR", "China") \
    .astype('str')

# 将数据列所有的NAN值填充为0
填充 = df.fillna({"学术声誉": 0,
                "雇主声誉": 0,
                "师生比": 0,
                "教员引用率": 0,
                "国际教师": 0,
                "国际学生": 0,
                "星级": 0,
                "总分": 0,
                })
填充.loc[:, "大学"] = 填充["大学"].str.replace("�?", "").replace("?", "")
填充.loc[:, "大学"] = 填充["大学"].str.replace("?", "")
new_df = 填充

# 开始页面
@app.route('/begin', methods=['GET'])
def begin_table() -> 'html':
    new_df = 填充.head(20)
    df_all = new_df.to_html()
    return render_template("base.html",
                           the_res=df_all,
                           data=new_df,
                           )

# 进入数据分析结果页面列表
@app.route('/neirong', methods=["GET", "POST"])
def hello_neirong() -> "html":
    return render_template("neirong.html", the_title="欢迎来到网站内容页面~")

# 排名top100的学校
@app.route('/top100_world', methods=['POST'])
def world() -> 'html':
    t_data = new_df[(df['排名'] <= 100)]
    new_data = t_data.sort_values(by="总分", ascending=True)
    university, score = [], []
    for idx, row in new_data.iterrows():
        if row['国家'] == 'China':
            university.append('🇨🇳 {}'.format(re.sub('（.*?）', '', row['大学'])))
        else:
            university.append(re.sub('（.*?）', '', row['大学']))
        score.append(opts.BarItem(name='', value=row['总分'], tooltip_opts=opts.TooltipOpts()))
        print(score)
        bar = (Bar()
               .add_xaxis(university)
               .add_yaxis('', score, category_gap='30%')
               .set_global_opts(title_opts=opts.TitleOpts(title="2021年世界大学TOP100排名",
                                                          pos_left="center",
                                                          title_textstyle_opts=opts.TextStyleOpts(font_size=20)),
                                datazoom_opts=opts.DataZoomOpts(range_start=70, range_end=100, orient='vertical'),
                                visualmap_opts=opts.VisualMapOpts(is_show=False, max_=100, min_=60, dimension=0,
                                                                  range_color=['#FF99CC', '#99CCFF']),
                                legend_opts=opts.LegendOpts(is_show=False),
                                xaxis_opts=opts.AxisOpts(is_show=False, is_scale=True),
                                yaxis_opts=opts.AxisOpts(axistick_opts=opts.AxisTickOpts(is_show=False),
                                                         axisline_opts=opts.AxisLineOpts(is_show=False),
                                                         axislabel_opts=opts.LabelOpts(font_size=12)))
               .set_series_opts(label_opts=opts.LabelOpts(is_show=True,
                                                          position='right',
                                                          font_style='italic'),
                                itemstyle_opts={"normal": {
                                    "barBorderRadius": [30, 30, 30, 30],
                                    'shadowBlur': 10,
                                    'shadowColor': 'rgba(120, 36, 50, 0.5)',
                                    'shadowOffsetY': 5,
                                }
                                }
                                ).reversal_axis())

    grid = (
        Grid(init_opts=opts.InitOpts(theme='purple-passion', width='1200px', height='800px'))
            .add(bar, grid_opts=opts.GridOpts(pos_right='10%', pos_left='20%'))
    )
    grid.render("example.html")
    with open("example.html", encoding="utf8", mode="r") as f:
        plot_all = "".join(f.readlines())
    data = new_data.to_html()

    return render_template('top100_world.html',
                           the_res=plot_all,
                           data=data, )

# 排名前500的中国大学
@app.route('/top500_china', methods=['POST'])
def china() -> 'html':
    China = new_df[new_df['国家'].isin(['China'])]
    data = China[(df['排名'] <= 500)]
    t_data = data.sort_values(by="总分", ascending=True)

    university, score = [], []
    for idx, row in t_data.iterrows():
        university.append(re.sub('（.*?）', '', row['大学']))
        score.append(opts.BarItem(name='', value=row['总分'], tooltip_opts=opts.TooltipOpts()))
        bar = (Bar()
               .add_xaxis(university)
               .add_yaxis('', score, category_gap='30%')
               .set_global_opts(title_opts=opts.TitleOpts(title="2021年TOP500世界大学中中国排名情况",
                                                          pos_left="center",
                                                          title_textstyle_opts=opts.TextStyleOpts(font_size=20)),
                                datazoom_opts=opts.DataZoomOpts(range_start=70, range_end=100, orient='vertical'),
                                visualmap_opts=opts.VisualMapOpts(is_show=False, max_=100, min_=60, dimension=0,
                                                                  range_color=['#FF99CC', '#99CCFF']),
                                legend_opts=opts.LegendOpts(is_show=False),
                                xaxis_opts=opts.AxisOpts(is_show=False, is_scale=True),
                                yaxis_opts=opts.AxisOpts(axistick_opts=opts.AxisTickOpts(is_show=False),
                                                         axisline_opts=opts.AxisLineOpts(is_show=False),
                                                         axislabel_opts=opts.LabelOpts(font_size=24)))
               .set_series_opts(label_opts=opts.LabelOpts(is_show=True,
                                                          position='right',
                                                          font_style='italic'),
                                itemstyle_opts={"normal": {
                                    "barBorderRadius": [30, 30, 30, 30],
                                    'shadowBlur': 10,
                                    'shadowColor': 'rgba(120, 36, 50, 0.5)',
                                    'shadowOffsetY': 5,
                                }
                                }
                                ).reversal_axis())

        grid = (
            Grid(init_opts=opts.InitOpts(theme='purple-passion', width='1200px', height='800px'))
                .add(bar, grid_opts=opts.GridOpts(pos_right='10%', pos_left='20%'))
        )
        grid.render("example.html")
        with open("example.html", encoding="utf8", mode="r") as f:
            plot_all = "".join(f.readlines())
        data = t_data.to_html()
    return render_template('top500_china.html',
                           the_res=plot_all,
                           data=data, )

# 各项指标之间的排名情况
@app.route('/target_list', methods=['POST'])
def target() -> 'html':
    排名top20的大学 = new_df[(new_df['排名'] <= 20)]
    指标排名 = 排名top20的大学.sort_values(by='总分', ascending=True)
    # 筛选数据目标（处理数据）
    数据处理 = 指标排名[['国家', '地区', '大学', '排名', '总分']]
    data = 数据处理.to_html()
    # 筛选目标
    target_list = ["学术声誉", "雇主声誉", "师生比", "教员引用率", "国际教师", "国际学生"]
    res = target_list
    x_data = list(set(pd.unique(数据处理['大学'])))
    y_data = list(set(pd.unique(数据处理['总分'])))
    bar = (
        Bar(init_opts=opts.InitOpts(theme='purple-passion'))
            .add_xaxis(x_data)
            .add_yaxis('', y_data)
            .set_global_opts(title_opts=opts.TitleOpts(title="2021年top20大学总分得分情况",
                                                       pos_left="center",
                                                       title_textstyle_opts=opts.TextStyleOpts(font_size=20)),
                             )
    )
    grid = (
        Grid(init_opts=opts.InitOpts(theme='purple-passion', width='1200px', height='800px'))
            .add(bar, grid_opts=opts.GridOpts(pos_right='10%', pos_left='20%'))
    )
    grid.render("example.html")
    with open("example.html", encoding="utf8", mode="r") as f:
        plot_all = "".join(f.readlines())
    return render_template("zhibiao.html",
                           target_lists=res,
                           data=data,
                           the_res=plot_all,
                           )


# 对指标进行筛选后的排名情况。
@app.route('/top20_target', methods=['POST'])
def shaixuan() -> 'html':
    target_list = ["学术声誉", "雇主声誉", "师生比", "教员引用率", "国际教师", "国际学生"]
    res = target_list
    choose = request.form["target_list"]
    if choose in target_list:
        排名top20的大学 = new_df[(new_df['排名'] <= 20)]
        指标排名 = 排名top20的大学.sort_values(by=choose, ascending=True)

    university, score = [], []
    for idx, row in 指标排名.iterrows():
        university.append(re.sub('（.*?）', '', row['大学']))
        score.append(opts.BarItem(name='', value=row[choose], tooltip_opts=opts.TooltipOpts()))
        bar = (Bar()
               .add_xaxis(university)
               .add_yaxis('', score, category_gap='30%')
               .set_global_opts(title_opts=opts.TitleOpts(title="2021年TOP20世界大学中" + choose + "排名情况",
                                                          pos_left="center",
                                                          title_textstyle_opts=opts.TextStyleOpts(font_size=20)),
                                datazoom_opts=opts.DataZoomOpts(range_start=70, range_end=100, orient='vertical'),
                                visualmap_opts=opts.VisualMapOpts(is_show=False, max_=80, min_=60, dimension=0,
                                                                  range_color=['#FF99CC', '#99CCFF']),
                                legend_opts=opts.LegendOpts(is_show=False),
                                xaxis_opts=opts.AxisOpts(is_show=False, is_scale=True),
                                yaxis_opts=opts.AxisOpts(axistick_opts=opts.AxisTickOpts(is_show=False),
                                                         axisline_opts=opts.AxisLineOpts(is_show=False),
                                                         axislabel_opts=opts.LabelOpts(font_size=24)))
               .set_series_opts(label_opts=opts.LabelOpts(is_show=True,
                                                          position='right',
                                                          font_style='italic'),
                                itemstyle_opts={"normal": {
                                    "barBorderRadius": [30, 30, 30, 30],
                                    'shadowBlur': 10,
                                    'shadowColor': 'rgba(120, 36, 50, 0.5)',
                                    'shadowOffsetY': 5,
                                }
                                }
                                ).reversal_axis())

        grid = (
            Grid(init_opts=opts.InitOpts(theme='purple-passion', width='1200px', height='800px'))
                .add(bar, grid_opts=opts.GridOpts(pos_right='10%', pos_left='20%'))
        )
        grid.render("example.html")
        with open("example.html", encoding="utf8", mode="r") as f:
            plot_all = "".join(f.readlines())
        data = 指标排名.to_html()
    return render_template('zhibiao.html',
                           the_res=plot_all,
                           target_lists=res,
                           data1=data, )


@app.route('/place', methods=['POST'])
def place() -> 'html':
    排名top100的大学 = new_df[(new_df['排名'] <= 100)]
    地区分类 = pd.unique(排名top100的大学['地区'])
    place_list = list(set(地区分类))
    地区分布 = 排名top100的大学.groupby(['地区']) \
        .agg({'大学': 'count'}) \
        .sort_values(['大学'], ascending=False) \
        .rename(columns={"大学": "大学数量"}) \
        .reset_index()
    # 地区大学数量分析
    x_data = 地区分布["地区"].to_list()
    y_data = 地区分布["大学数量"].to_list()
    bar = (
        Bar(init_opts=opts.InitOpts(theme='purple-passion'))
            .add_xaxis(x_data)
            .add_yaxis('', y_data)
            .set_global_opts(title_opts=opts.TitleOpts(title="2021年各大地区top100大学数量分布",
                                                       pos_left="center",
                                                       title_textstyle_opts=opts.TextStyleOpts(font_size=20)),
                             )
    )
    grid = (
        Grid(init_opts=opts.InitOpts(theme='purple-passion', width='1200px', height='800px'))
            .add(bar, grid_opts=opts.GridOpts(pos_right='10%', pos_left='20%'))
    )
    grid.render("example.html")
    with open("example.html", encoding="utf8", mode="r") as f:
        plot_all = "".join(f.readlines())


    # 地区大学数量分析
    cate = 地区分布["地区"].to_list()
    data2 = 地区分布["大学数量"].to_list()

    pie = (Pie(init_opts=opts.InitOpts(theme='purple-passion'))
           .add('', [list(z) for z in zip(cate, data2)])
           .set_global_opts(title_opts=opts.TitleOpts(title="2021年各大地区top100大学数量分布",
                                                      pos_bottom="left",
                                                      title_textstyle_opts=opts.TextStyleOpts(font_size=20)),
                            )
           )

    grid2 = (
        Grid(init_opts=opts.InitOpts(theme='purple-passion', width='1200px', height='800px'))
            .add(pie, grid_opts=opts.GridOpts(pos_right='10%', pos_left='20%'))
    )
    grid2.render("example2.html")
    with open("example2.html", encoding="utf8", mode="r") as f:
        plot2_all = "".join(f.readlines())
        data = 地区分布.to_html()
    return render_template('place.html',
                           the_res=plot_all,
                           res=plot2_all,
                           data=data,
                          )


@app.route('/world_map', methods=['POST'])
def map() -> 'html':
    t_data = new_df[(new_df['排名'] <= 1000)]
    tdata = t_data.groupby(['国家'])['大学'].count().reset_index()
    tdata.columns = ['国家', 'num']
    data = tdata.sort_values(by="num", ascending=True)

    data_pair = []
    for idx, row in data.iterrows():
        if row['国家'] in ['China (Mainland)', 'Hong Kong SAR', 'Taiwan', 'Macau SAR']:
            data_pair.append(['China', row['num']])
        else:
            data_pair.append([row['国家'], row['num']])
    map_ = (
        Map()
            .add("", data_pair, 'world')
            .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
            .set_global_opts(visualmap_opts=opts.VisualMapOpts(max_=160, is_show=True,
                                                               is_piecewise=True,
                                                               range_color=['#339966', '#CC99FF', '#666699']))
    )
    grid = (
        Grid(init_opts=opts.InitOpts( width='1200px', height='1000px'))
            .add(map_, grid_opts=opts.GridOpts(pos_right='10%', pos_left='20%'))
    )
    grid.render("example.html")
    with open("example.html", encoding="utf8", mode="r") as f:
        plot_all = "".join(f.readlines())

    return render_template('worldmap.html',
                           the_res=plot_all,
                           )


@app.route('/country', methods=['POST'])
def countrys() -> 'html':
    排名top100的大学 = new_df[(new_df['排名'] <= 100)]
    country_list =list(set(pd.unique(排名top100的大学['国家'])))
    # 国家top100大学分布情况
    国家分布 = 排名top100的大学.groupby(['国家']) \
        .agg({'大学': 'count'}) \
        .sort_values(['大学'], ascending=False) \
        .rename(columns={"大学": "大学数量"}) \
        .reset_index()
    data=国家分布

    # 国家大学数量分析
    x_data = 国家分布["国家"].to_list()
    y_data = 国家分布["大学数量"].to_list()
    y_data_line = 国家分布["大学数量"].to_list()
    bar = (
        Bar(init_opts=opts.InitOpts(theme='purple-passion'))
            .add_xaxis(x_data)
            .add_yaxis('', y_data)
            .set_global_opts(title_opts=opts.TitleOpts(title="2021年各国top100大学数量分布",
                                                       pos_left="center",
                                                       title_textstyle_opts=opts.TextStyleOpts(font_size=20)),
                             )
    )

    line = (Line(init_opts=opts.InitOpts(theme='purple-passion'))
            .add_xaxis(x_data)
            .add_yaxis('', y_data_line)
            )

    overlap = bar.overlap(line)
    grid = (
        Grid(init_opts=opts.InitOpts( width='1200px', height='800px'))
            .add(overlap, grid_opts=opts.GridOpts(pos_right='10%', pos_left='20%'))
    )
    grid.render("example.html",theme='purple-passion')
    with open("example.html", encoding="utf8", mode="r") as f:
        plot_all = "".join(f.readlines())

    return render_template('country.html',
                           the_res=plot_all,
                           data=data ,
                           )


if __name__ == '__main__':
    app.run(debug=True)
